#include <HardwareSerial.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// 📡 GPS 串口定义（M210Z）
HardwareSerial GPS(1);  // UART1，用于接 M210Z 模块
#define GPS_RX 1  // IO1 ← GPS TXD
#define GPS_TX 0  // IO0 → GPS RXD（可选）

// OLED 引脚定义
#define OLED_SCL 6
#define OLED_SDA 5
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// 🌐 WiFi 配置
const char* ssid = "BD3ND_2.4G";
const char* password = "12345678abc";

// 🌐 APRS 上传服务器信息
const char* callsign = "BD3ND-10";  // 替换为你的呼号
const char* aprsServer = "rotate.aprs.net";
const uint16_t aprsPort = 14580;
const char symTable = '/';   // 使用符号表 A
const char symChar  = '>';   // "车" 图标

WiFiClient client;
uint16_t passcodeNum = 0;
unsigned long lastSend = 0;
const unsigned long sendInterval = 5UL * 60UL * 1000UL; // 5 分钟间隔
unsigned long lastDebug = 0;

// 🛰️ 实时定位数据
float latitude = 0.0;
float longitude = 0.0;
String latestTime = "";

void connectToWiFi() {
  Serial.print("[WiFi] 连接到 WiFi 网络："); Serial.println(ssid);
  WiFi.begin(ssid, password);
  int retry = 0;
  while (WiFi.status() != WL_CONNECTED && retry < 20) {
    delay(500);
    Serial.print(".");
    retry++;
  }
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\n[WiFi] 成功连接，IP地址: " + WiFi.localIP().toString());
  } else {
    Serial.println("\n[WiFi] 连接失败，请检查SSID与密码");
  }
}

// —— APRS-IS Passcode 计算 ——
uint16_t calculatePasscode(const char* call) {
  String root = String(call);
  int dash = root.indexOf('-');
  if (dash > 0) root = root.substring(0, dash);
  root.toUpperCase();
  uint8_t hi = 0x73, lo = 0xE2;
  size_t len = root.length();
  for (size_t i = 0; i < len; i += 2) {
    uint8_t c1 = root.charAt(i);
    uint8_t c2 = (i + 1 < len) ? root.charAt(i + 1) : 0;
    hi ^= c1;
    lo ^= c2;
  }
  return (uint16_t)(((hi & 0x7F) << 8) | lo);
}

// —— 坐标格式化函数 ——
String aprsLat(float lat) {
  char buf[16];
  char hemi = (lat >= 0) ? 'N' : 'S';
  lat = fabs(lat);
  int deg = int(lat);
  float min = (lat - deg) * 60.0;
  snprintf(buf, sizeof(buf), "%02d%05.2f%c", deg, min, hemi);
  return String(buf);
}
String aprsLon(float lon) {
  char buf[16];
  char hemi = (lon >= 0) ? 'E' : 'W';
  lon = fabs(lon);
  int deg = int(lon);
  float min = (lon - deg) * 60.0;
  snprintf(buf, sizeof(buf), "%03d%05.2f%c", deg, min, hemi);
  return String(buf);
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("[系统] 初始化串口");

  GPS.begin(9600, SERIAL_8N1, GPS_RX, GPS_TX);
  delay(500);
  Serial.println("[系统] GPS 串口已开启");

  Wire.begin(OLED_SDA, OLED_SCL);
  Wire.setClock(400000);  // 设置 I2C 速率为 400kHz
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("[错误] OLED 初始化失败！"));
  } else {
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);
    display.println("[系统] OLED 启动");
    display.display();
  }

  passcodeNum = calculatePasscode(callsign);
  connectToWiFi();
}

void loop() {
  static String line = "";
  while (GPS.available()) {
    char c = GPS.read();
    if (c == '\n') {
      if (line.startsWith("$BDRMC") || line.startsWith("$GNRMC")) {
        parseRMC(line);
      }
      line = "";
    } else {
      line += c;
    }
  }
  if (millis() - lastSend >= sendInterval && latitude != 0.0 && longitude != 0.0) {
    sendAprsPosition();
    lastSend = millis();
  }
  if (millis() - lastDebug > 10000) {
    lastDebug = millis();
    Serial.printf("[状态] 定位有效: %.5f, %.5f\n", latitude, longitude);
    display.clearDisplay();
    display.setCursor(0, 0);
    display.print("Lat: "); display.println(latitude, 5);
    display.print("Lon: "); display.println(longitude, 5);
    display.print("Time: "); display.println(latestTime);
    display.print("SSID: "); display.println(ssid);
    display.display();
  }
}

void parseRMC(String rmc) {
  int idx = 0;
  String parts[20];
  while (rmc.length() > 0 && idx < 20) {
    int comma = rmc.indexOf(',');
    if (comma == -1) {
      parts[idx++] = rmc;
      break;
    } else {
      parts[idx++] = rmc.substring(0, comma);
      rmc = rmc.substring(comma + 1);
    }
  }

  if (parts[2] == "A") {
    latestTime = parts[1];
    float rawLat = parts[3].toFloat();
    float rawLon = parts[5].toFloat();
    int degLat = int(rawLat / 100);
    int degLon = int(rawLon / 100);
    float minLat = rawLat - degLat * 100;
    float minLon = rawLon - degLon * 100;
    latitude = degLat + minLat / 60.0;
    longitude = degLon + minLon / 60.0;
    if (parts[4] == "S") latitude = -latitude;
    if (parts[6] == "W") longitude = -longitude;
  }
}

void sendAprsPosition() {
  if (!client.connected()) {
    if (!client.connect(aprsServer, aprsPort)) {
      Serial.println("❌ 连接 APRS-IS 失败");
      return;
    }
    client.printf("user %s pass %u vers ESP32-APRS 1.0\r\n", callsign, passcodeNum);
    Serial.printf("✔ 登录 APRS-IS 成功 (passcode: %u)\n", passcodeNum);
  }
  String packet = String(callsign) + ">APRS,TCPIP*:=" + aprsLat(latitude) + symTable + aprsLon(longitude) + symChar + " ESP32 APRS";
  client.println(packet);
  Serial.println("✉ 已发送: " + packet);
  Serial.println("[调试] 上传 APRS 报文内容：" + packet);
}
